#include<stdio.h>
#include<stdlib.h>
#include<wait.h>
#include<unistd.h>
#include<string.h>
#include<fcntl.h>

int main()
{
  while(1)
  {
    //增加一个shell提示
    printf("[dev@minishell]$ ");
    fflush(stdout);//刷新标准输出缓冲区
    //1.等待标准输入
    char buf[1024]={0};
    fgets(buf,1023,stdin);
    buf[strlen(buf)-1]='\0';    //最后一个输入变成换行
    //1.5.解析重定向
    //ls -l > a.txt
    char* ptr = buf;
    int redirect_flag =0;
    char* redirect_file = NULL;
    while(*ptr != '\0')
    {
       if(*ptr == '>')
       {
          redirect_flag = 1; //这是清空重定向
          *ptr = '\0';  //将>替换成结尾标志，则命令的解析就到此为止了
          ptr++;
          if(*ptr == '>')
          { //有第二个>就是追加重定向
            redirect_flag = 2; 
            ptr++;
          }
          while(*ptr == ' ' && *ptr != '\0')
          {
            ptr++;     //将a.txt之前的空格走完
          }
          redirect_file = ptr;  //redirect_file这个指针指向了a.txt的a
          while(*ptr != ' ')
          {
            ptr++;     //将a.txt走完
          }
          *ptr= '\0';
       }
       ptr++;
    }
    //2.对数据进行解析
    char* argv[32]={NULL};
    int argc = 0;
    ptr = buf;
    while(*ptr != '\0')
    {
      if(*ptr != ' ')
      {
        argv[argc] = ptr;
        argc++;
        while(*ptr != ' ' && *ptr != '\0')
        {
          ptr++;
        }
        *ptr = '\0';
      }
      ptr++;
    }
    argv[argc] = NULL;  //最后一个参数的下一个位置置NULL
    
    //3.创建子进程
    //4.进程替换
    pid_t pid = fork();
    if(pid == 0)
    {
      if(redirect_flag == 1){ //清空重定向
        int fd = open(redirect_file, O_WRONLY|O_CREAT|O_TRUNC,0664);
        dup2(fd,1);    //将标准输入重定向到fd中，原本打印的数据就会被写入到文件中
      }else if(redirect_flag == 2){   //追加重定向
        int fd = open(redirect_file, O_WRONLY|O_CREAT|O_APPEND,0664);
        dup2(fd,1);    //将标准输入重定向到fd中，原本打印的数据就会被写入到文件中
      }
      //execvp(char* file,char* argv[]);  file----新程序名称
      execvp(argv[0],(char**)argv); //如果pid是子进程的，就进行程序替换，去执行别的程序
      //如果替换成功了，就去执行别的程序了，没有返回值，且下面的代码也不会执行
      //如果替换失败，就执行下面的代码
      perror("execvp error");    //打印上一次系统调用接口使用的错误原因
      exit(0);         //替换失败就不能再继续运行了，退出程序
    }
    //5.进程等待
    wait(NULL);

  }

  return 0;
}
